package com.bkhech.nettyhttp.client;

import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;

import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;

/**
 * SslContextFactoryForClient
 * 客户端生产环境中需安全的证书管理策略示例
 * <p>
 * 1. 获取有效的服务器证书
 * 首先，你需要从CA（证书颁发机构）获取有效的服务器证书和相应的私钥。
 * 这通常是通过购买SSL证书或从可信任的CA获取免费证书来完成的。
 * <p>
 * 2. 创建SSL上下文
 * 使用有效的服务器证书和私钥来创建SSL上下文
 *
 * @author guowm
 * @date 2024/4/1
 */
public class SslContextFactoryForClient {
    //Java特有的密钥存储格式
    private static final String KEY_STORE_TYPE = "JKS";
    // Bouncy Castle 的 X.509 证书管理器。
    private static final String TRUST_MANAGER_TYPE = "X509";
    //JKS 格式的服务器证书的实际路径。
    private static final String TRUST_STORE_PATH = "/path/to/your/truststore.jks";
    //JKS 格式的服务器证书的密码。
    private static final String TRUST_STORE_PASSWORD = "your_truststore_password";

    public static SslContext getSslContext() throws Exception {
        TrustManagerFactory trustManagerFactory = buildTrustManagerFactory();

        return SslContextBuilder.forClient()
                .trustManager(trustManagerFactory)
                .build();
    }

    private static TrustManagerFactory buildTrustManagerFactory() throws Exception {
        final KeyStore trustStore = loadKeyStore(TRUST_STORE_PATH, TRUST_STORE_PASSWORD);

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TRUST_MANAGER_TYPE);
        trustManagerFactory.init(trustStore);
        return trustManagerFactory;
    }

    private static KeyStore loadKeyStore(String storePath, String storePassword) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
        KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
        try (FileInputStream fis = new FileInputStream(storePath)) {
            keyStore.load(fis, storePassword.toCharArray());
        }
        return keyStore;
    }
}
